<?php

namespace Framework\Foundation\Event;

use Framework\Foundation\Event\Interfaces\EventListenerInterface;
use Framework\Foundation\Queue\Interfaces\QueueHandler;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\EventDispatcher\ListenerProviderInterface;
use Psr\EventDispatcher\StoppableEventInterface;

class EventDispatcher implements EventDispatcherInterface
{
    /**
     * @var ListenerProviderInterface
     */
    protected $provider;
    /**
     * @var QueueHandler
     */
    protected $queueHandler;

    public function __construct(ListenerProviderInterface $provider, $queueHandler = null)
    {
        $this->provider = $provider;
        $this->queueHandler = $queueHandler;
    }

    public function dispatch(object $event)
    {
        /**
         * @var $listeners EventListenerInterface[];
         */
        $listeners = $this->provider->getListenersForEvent($event);

        $asynchronous = [];
        foreach ($listeners as $listener) {
            if ($listener->asynchronous()) {
                $asynchronous[] = get_class($listener);
                continue;
            }

            if ($event->isPropagationStopped()) {
                throw new \Exception("event stopped in :" . get_class($listener));
            }

            $listener->handleEvent($event);
        }

        if (empty($asynchronous)) {
            return true;
        }

        if (empty($this->queueHandler)) {
            throw new \Exception("未配置队列");
        }

        if (!empty($asynchronous)) {
            $this->queueHandler->push(
                json_encode(['event' => serialize($event), 'listener' => $asynchronous])
            );
        }

        return true;
    }
}
